雨下個不停阿,但是待在家裡感覺會廢掉,還是出門尋找咖啡廳...
早上還是要寫作業,先整理一下dependency,把xmlrun發佈到npm,不然node/npm降版會有問題...
接下來開始繼續寫單元測試~~只寫了一半,就要吃午飯了...OK,下午繼續
下午看了一下文件,確認從OPCUA Server讀取資料節點的方式,看到不少東西...node-opcua官方文件很缺乏說明文字,反而在github上的issue track裡面有不少人貢獻code snippet XD,沒有仔細google還不會找到。知道找東西的方向,以後就方便了(可以寫整合測試?)
晚上回頭比較一下pptx viewer的資料,看起來前幾天調整過的xml to json的剖析器產出的格式大致上沒錯,現在需要的是把東西匯總起來成為單一的json。另外,我發現以前手賤,改了轉換後的名稱...tag名稱有sld的會改成slide,r:id的會改成rid之類,這個可能直接去調整viewer比較好。
彙整要怎麼做呢?處理的大致上都是ppt/底下的檔案...副檔名是.rels的把他的副檔名去掉當作key,內容則是從xml轉出的東西。副檔名是.xml的,則把presentation.xml的內容匯總到presentation這個key下面,其他的則依照ppt之下的目錄名來當作key,xml檔名當作下一層的key,然後把轉換後的json物件指派給這個key就可以。
媒體的部分會需要另外處理,今天先不管他。首先加一行:
let data = {relations:{},presentation:{},themes:{},slideMasters:{},slideLayouts:{},slides:{}};
.rels的資訊彙整到relations裡面,ppt/presentation.xml的資訊彙整到presentation,其他則根據目錄及xml檔名各自處理。程式改成:
<!DOCTYPE html>
<html>
<head>
<title>file reader</title>
<style>
.dropable {
width: 99%;
height: 100px;
background-color: #369;
color: white;
border: solid 3px gray;
border-radius: 5px;
padding: 5px 5px 5px 5px;
}
.message {
width: 99%;
background-color: #ddd;
border: solid 1px gray;
border-radius: 5px;
overflow: auto;
}
.preview {
font-size: 10px;
}
</style>
</head>
<body>
<div id="target" class="dropable">
<select id="encoding">
<option value="utf-8">utf-8</option>
<option value="big5">big5</option>
<option value="gb2312">gb2312</option>
<option value="shift-jis">shift-jis</option>
</select>
<input type="file" id="file" />
<div id="console"></div>
</div>
<div id="panel" class="message"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.11/pako_inflate.min.js"></script>
<script src="lib/zipfs.js"></script>
<script src="node_modules/xmlrun/index.js"></script>
<script>
var _target = document.getElementById('target');
var _message = document.getElementById('panel');
var _file = document.getElementById('file');
_file.onchange = function(e) {
clearlog();
if (this.files.length > 0) {
var reader = new FileReader();
reader.onload = (e) => {
var buffer = e.target.result;
log('file size: ' + buffer.byteLength);
let encoding = document.getElementById('encoding').value;
let start = new Date().getTime();
zipfs(buffer, pako.inflateRaw, encoding, (err, files) => {
let data = {relations:{},presentation:{},themes:{},slideMasters:{},slideLayouts:{},slides:{}};
if (!!err) return console.log(err);
log(`in callback: ${files.length} files extracted.`);
log(`${(new Date().getTime()-start)} ms`);
let str = '<table border="1" cellspacing="0" cellpadding="5" width="99%"><tr><th>file name</th><th>buffer length</th><th>last modified date</th><th>last modified time</th><th>compressed size</th><th>uncompressed size</th></tr>';
files.forEach(file => {
str += `<tr><td>${file.file_name}</td><td>${file.content.length}</td><td>${zipfs.formatMSDOSDate(file.last_modified_date)}</td><td>${zipfs.formatMSDOSTime(file.last_modified_time)}</td><td>${file.compressed_size}</td><td>${file.uncompressed_size}</td></tr>`;
str += `<tr><td colspan="6" class="preview" style="overflow-x:hidden">`;
if (checkExt(file.file_name, '.rels') && file.file_name.length > 5) {
let runner = xmlnode(zipfs.uintToString(file.content));
runner.setRunner('default', function(target) {
if(!!target.child) {
return target.child.reduce((acc, cur) => {
Object.assign(acc, cur.run());
return acc;
}, {})
}
else return {};
});
runner.setRunner('Relationship', target => {
let result = {};
result[target.attr['Id']] = target.attr['Target'];
result[target.attr['Target']] = target.attr['Id'];
return result;
});
data.relations[file.file_name.substr(0, file.file_name.length-5)] = runner.run();
}
if (checkExt(file.file_name, '.xml')) {
let runner = xmlnode(zipfs.uintToString(file.content));
runner.setRunner('default', function(target) {
let result = {};
if(!!target.attr) {
result = Object.keys(target.attr).reduce((pre, cur) => {
pre[cur] = target.attr[cur];
return pre;
}, {});
}
if(!!target.val) result._value = target.val;
if(!!target.child && Array.isArray(target.child) && target.child.length > 0) {
target.child.forEach(c => {
if(!result[c.tag]) {
result[c.tag] = c.run();
} else {
if(Array.isArray(result[c.tag])) {
result[c.tag].push(c.run());
} else {
let _t = result[c.tag];
result[c.tag] = [];
result[c.tag].push(_t);
result[c.tag].push(c.run());
}
}
});
}
return result;
});
if(file.file_name === 'ppt/presentation.xml') {
data.presentation = runner.run();
} else {
let paths = file.file_name.split('/');
if(Object.keys(data).indexOf(paths[1]) > -1) {
data[paths[1]][file.file_name] = runner.run();
}
}
}
if (checkExt(file.file_name, '.jpeg') || checkExt(file.file_name, '.jpg')) {
let im = new Image();
im.src = `data:image/jpeg;base64,${zipfs.arrayBufferToBase64(file.content)}`;
if(im.width > 1024) {
str += `<img width="1024px" src="data:image/jpeg;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
} else {
str += `<img src="data:image/jpeg;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
}
}
if (checkExt(file.file_name, '.png')) {
let im = new Image();
im.src = `data:image/png;base64,${zipfs.arrayBufferToBase64(file.content)}`;
if(im.width > 1024) {
str += `<img width="1024px" src="data:image/png;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
} else {
str += `<img src="data:image/png;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
}
}
if (checkExt(file.file_name, '.mp3')) {
str += '<audio controls type="audio/mpeg" src="data:audio/mp3;base64,' +
zipfs.arrayBufferToBase64(file.content) + '">';
}
str += '</td></tr>';
});
str += `<tr><td colspan="6" class="preview" style="overflow-x:hidden"><pre>${JSON.stringify(data, null, 2)}</pre></td></tr>`;
str += '</table>';
document.getElementById('panel').innerHTML = str;
});
};
reader.readAsArrayBuffer(this.files[0]);
}
function checkExt(name, ext) {
return name.lastIndexOf(ext) === name.length - ext.length;
}
function log(msg) {
document.getElementById('console').innerHTML += `<br />${msg}`;
}
function clearlog() {
document.getElementById('console').innerHTML = '';
}
}
</script>
</body>
</html>
.rels及.xml就不顯示內容,而匯總到最後才顯示匯總的結果。網頁一開始:
後面顯示匯總的json:
其實仔細觀察,裡面還存在一些細微的差異,另外,themes底下的檔案不知道為什麼沒有匯總進來,這些就留到明天吧。
謝謝分享!連續潮濕的天氣,濕氣確實令人會感到昏倦、特別累,記得定期除濕開抽濕機,屆時編程都寫得更精目、清晰,加油呀!